package com.sduept.nwld.dataserver.controller.fault.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.esms.common.util.StringUtils;
import com.sduept.bigdata.fault.entity.FaultDetail;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@Slf4j
public class OmsExcelDataListener  extends AnalysisEventListener<ImportOmsDTO> {




    // 记录错误行信息
    private StringBuilder errorInfos = new StringBuilder();


    private Map<Integer,ImportOmsDTO> map = new HashMap<>();

    private  String errorContent = "文件中第#{行数}行数据#{错误内容};";


    private List<FaultDetail> faultDetails = new ArrayList<>();




    public OmsExcelDataListener(StringBuilder errorInfos) {
        super();
        this.errorInfos = errorInfos;
    }

    @Override
    public void invoke(ImportOmsDTO data, AnalysisContext context) {
        Integer row  = context.readRowHolder().getRowIndex();
        map.put(row, data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        for(Entry<Integer,ImportOmsDTO> entry:map.entrySet()) {
            ImportOmsDTO omsDto = entry.getValue();
            if(isDataComplete(omsDto,entry.getKey()+1)) {//判断数据是否符合要求-电压等级-动作过程
                FaultDetail fd = new FaultDetail();
                fillFaultDetailData(omsDto,fd);
                faultDetails.add(fd);
            }
        }
        log.error("上传失败数据："+errorInfos);
    }

    /**
     * 完善faultDetail数据
     * @param omsDto
     * @param fd
     */
    private void fillFaultDetailData(ImportOmsDTO omsDto, FaultDetail fd) {
        // TODO Auto-generated method stub
        fd.setActionProcess(omsDto.getActionProcess());
        fd.setActualQuickActNum(omsDto.getActualQuickActNum()==null?"":omsDto.getActualQuickActNum());
        Float[] actTimes =  getActTime(omsDto.getActionProcess());//保护动作时间 故障持续时间 断路器动作时间
        if(actTimes==null) {
            return;
        }
        fd.setBreakerActionTime(actTimes[2]);
        fd.setFaultContinueTime(actTimes[1]);
        fd.setPrimaryProtectTime(actTimes[0]);
        fd.setEtype(omsDto.getEType());
        fd.setFaultDate(omsDto.getFaultDate());
        fd.setFaultEquipment(omsDto.getFaultEquipment());
        fd.setFaultPhase(omsDto.getFaultPhase());
        fd.setFaultTime(omsDto.getFaultTime());
        fd.setFaultType(omsDto.getFaultType());
        fd.setQuickProtectStatus(omsDto.getQuickProtectStatus());
        fd.setReclosingStatus(omsDto.getReclosingStatus());
        fd.setStationName(getStationName(omsDto.getActionProcess()));
        fd.setVoltage(getVoltage(omsDto.getVoltage()));
    }

    private Float getVoltage(String voltage) {
        String value = voltage.replaceAll("[a-zA-Z]","");
        return Float.valueOf(value);
    }

    private String getStationName(String actionProcess) {
        String point = getPointByActionProcess(actionProcess);
        String stationName = null;
        try {
            stationName = actionProcess.substring(0, actionProcess.indexOf(point));
        }catch(Exception e) {
            errorInfos.append("动作过程为："+actionProcess+"的数据不符合要求");
            return null;
        }
        if(StringUtils.isBlank(stationName)) {
            return "";
        }
        return stationName;
    }

    private String getPointByActionProcess(String actionProcess) {
        String point = null;
        if(actionProcess.contains("：")) {
            point = "：";
        }else if(actionProcess.contains(":")) {
            point = ":";
        }
        return point;
    }

    /*
     * 根据动作过程解析动作时间
     */
    private Float[] getActTime(String actionProcess) {
        String process = null;
        if(actionProcess.contains("：")||actionProcess.contains(":")) {
            String point = getPointByActionProcess(actionProcess);
            String[] arr = actionProcess.split(point);
            process = arr[1];
        }else {
            process = actionProcess;
        }
        String protectStr = "保护";
        String breaker = "开关";
        String dh = "断弧";
        String ms = "ms";
        Float[] actTimes = new Float[3];//保护动作时间 故障持续时间 断路器动作时间
        Float protectActTime = null;
        Float faultContinueTime = null;
        Float breakActTime = null;
        try {
            String protectT = process.substring(process.indexOf(protectStr)+2, process.indexOf(ms));
            String kgStr = process.substring(process.indexOf(breaker), process.indexOf(dh));
            String faultContinueT = kgStr.substring(kgStr.indexOf(breaker)+2, kgStr.indexOf(ms));
            protectActTime = Float.valueOf(protectT.trim());
            faultContinueTime = Float.valueOf(faultContinueT.trim());
        }catch(Exception e){
            errorInfos.append("动作过程为："+actionProcess+"的数据不符合要求;");
            return null;
        }
        breakActTime = faultContinueTime-protectActTime;
        actTimes[0]=protectActTime;
        actTimes[1] = faultContinueTime;
        actTimes[2] = breakActTime;
        return actTimes;
    }

    /**
     * 数据是否完整
     * @param omsDto
     * @param row
     */
    private boolean isDataComplete(ImportOmsDTO omsDto, Integer row) {
        // TODO Auto-generated method stub
        String voltage = omsDto.getVoltage();
        if(!voltage.contains("220")) {
            errorInfos.append(errorContent.replace("#{行数}", row.toString()).replace("#{错误内容}", "电压等级不是220KV"));
            return false;
        }
        if(StringUtils.isBlank(omsDto.getActionProcess())) {
            errorInfos.append(errorContent.replace("#{行数}", row.toString()).replace("#{错误内容}", "无动作过程"));
            return false;
        }
        if(!omsDto.getActionProcess().contains("保护")||!omsDto.getActionProcess().contains("开关")) {
            errorInfos.append(errorContent.replace("#{行数}", row.toString()).replace("#{错误内容}", "动作过程信息不完整"));
            return false;
        }

        return true;
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.error("解析失败，继续解析下一行");
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            int rowIndex = excelDataConvertException.getRowIndex()+1;
            int colIndex = excelDataConvertException.getColumnIndex()+1;
            errorInfos.append("第"+rowIndex+"行，第"+colIndex+"列解析异常；");
            log.error("第"+rowIndex+"行，第"+colIndex+"列解析异常");
        }
    }

    public List<FaultDetail> getFaultDetails() {
        return faultDetails;
    }

    public void setFaultDetails(List<FaultDetail> faultDetails) {
        this.faultDetails = faultDetails;
    }



}
